home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / MacPerl 5.0.3 / MacPerl Source ƒ / MacPerl5 / MPSave.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-18  |  17.9 KB  |  944 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPSave.c            -    Handle all the runtimes
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPSave.c,v $
  12. Revision 1.1  1994/02/27  23:01:45  neeri
  13. Initial revision
  14.  
  15. Revision 0.1  1993/10/03  00:00:00  neeri
  16. Compiles correctly
  17.  
  18. *********************************************************************/
  19.  
  20. #include <Errors.h>
  21. #include <Resources.h>
  22. #include <PLStringFuncs.h>
  23. #include <LowMem.h>
  24. #include <Folders.h>
  25. #include <Finder.h>
  26. #include <TFileSpec.h>
  27.  
  28. #include "MPSave.h"
  29. #include "MPGlobals.h"
  30. #include "MPFile.h"
  31. #include "MPUtils.h"
  32.  
  33. #if defined(powerc) || defined (__powerc)
  34. #pragma options align=mac68k
  35. #endif
  36.  
  37. #define SERsrcBase    32700
  38.  
  39. typedef struct {
  40.     OSType            version; 
  41.     OSType            id;
  42.     OSType            fType;
  43.     OSType            fCreator;
  44.     
  45.     unsigned            wantsBundle     : 1;
  46.     unsigned            hasCustomIcon     : 1;
  47. } SEPackage, ** SEPackageHdl;
  48.  
  49. typedef struct {
  50.     OSType    type;
  51.     OSType    realType;
  52.     short        id;
  53.     short        realID;
  54. } ShoppingList, ** ShoppingListHdl;
  55.  
  56. typedef struct {
  57.     OSType    type;
  58.     short        id;
  59. } OwnerList;
  60.  
  61. #if defined(powerc) || defined (__powerc)
  62. #pragma options align=reset
  63. #endif
  64.  
  65. typedef struct {
  66.     OSType            id;
  67.     OSType            fType;
  68.     OSType            fCreator;
  69.     StringHandle    name;
  70.     Boolean            wantsBundle;
  71.     Boolean            hasCustomIcon;
  72.     FSSpec            file;
  73. } SaveExtension;
  74.  
  75. typedef struct {
  76.     short                count;
  77.     SaveExtension    ext[1];
  78. } SERec, * SEPtr, ** SEHdl;
  79.  
  80. SEHdl            SaveExtensions    =    nil;
  81. OSType **    FileTypeH = nil;
  82. OSType *     MacPerlFileTypes;
  83. short            MacPerlFileTypeCount;
  84.  
  85. OwnerList noOwner[] = {
  86.     0, 0
  87. };
  88.  
  89. OwnerList ancientOwner[] = {
  90.     'ALRT', 256,
  91.     'ALRT', 257,
  92.     'ALRT', 262,
  93.     'ALRT', 266,
  94.     'ALRT', 270,
  95.     'ALRT', 274,
  96.     'ALRT', 300,
  97.     'ALRT', 302,
  98.     'ALRT', 3850,
  99.     'BNDL', 128,
  100.     'CNTL', 192,
  101.     'CODE', 0,
  102.     'CODE', 1,
  103.     'CODE', 2,
  104.     'CODE', 3,
  105.     'CODE', 4,
  106.     'CODE', 5,
  107.     'CODE', 6,
  108.     'CODE', 7,
  109.     'CODE', 8,
  110.     'CODE', 9,
  111.     'CODE', 10,
  112.     'CODE', 11,
  113.     'CODE', 12,
  114.     'CODE', 13,
  115.     'CODE', 14,
  116.     'CODE', 15,
  117.     'CODE', 16,
  118.     'CODE', 17,
  119.     'CODE', 18,
  120.     'CODE', 19,
  121.     'CODE', 20,
  122.     'CODE', 21,
  123.     'CODE', 22,
  124.     'CODE', 23,
  125.     'CODE', 24,
  126.     'CODE', 25,
  127.     'CODE', 26,
  128.     'CODE', 27,
  129.     'CODE', 28,
  130.     'CODE', 29,
  131.     'CODE', 30,
  132.     'CODE', 31,
  133.     'CODE', 32,
  134.     'CODE', 33,
  135.     'CODE', 34,
  136.     'CODE', 35,
  137.     'CODE', 36,
  138.     'CODE', 37,
  139.     'CODE', 38,
  140.     'CODE', 39,
  141.     'CODE', 40,
  142.     'CODE', 41,
  143.     'CODE', 42,
  144.     'CODE', 43,
  145.     'CODE', 44,
  146.     'CODE', 45,
  147.     'CODE', 46,
  148.     'CODE', 47,
  149.     'CODE', 48,
  150.     'CODE', 49,
  151.     'CODE', 50,
  152.     'CODE', 51,
  153.     'CURS', 128,
  154.     'CURS', 129,
  155.     'CURS', 130,
  156.     'CURS', 131,
  157.     'CURS', 132,
  158.     'CURS', 144,
  159.     'CURS', 145,
  160.     'CURS', 146,
  161.     'CURS', 147,
  162.     'CURS', 148,
  163.     'CURS', 160,
  164.     'CURS', 161,
  165.     'CURS', 162,
  166.     'CURS', 163,
  167.     'DITL', 192,
  168.     'DITL', 256,
  169.     'DITL', 257,
  170.     'DITL', 258,
  171.     'DITL', 262,
  172.     'DITL', 266,
  173.     'DITL', 270,
  174.     'DITL', 274,
  175.     'DITL', 300,
  176.     'DITL', 302,
  177.     'DITL', 320,
  178.     'DITL', 384,
  179.     'DITL', 385,
  180.     'DITL', 386,
  181.     'DITL', 387,
  182.     'DITL', 512,
  183.     'DITL', 1005,
  184.     'DITL', 2001,
  185.     'DITL', 2002,
  186.     'DITL', 2003,
  187.     'DITL', 2010,
  188.     'DITL', 2020,
  189.     'DITL', 3850,
  190.     'DITL', 10240,
  191.     'DLOG', 192,
  192.     'DLOG', 258,
  193.     'DLOG', 320,
  194.     'DLOG', 384,
  195.     'DLOG', 512,
  196.     'DLOG', 1005,
  197.     'DLOG', 2001,
  198.     'DLOG', 2002,
  199.     'DLOG', 2003,
  200.     'DLOG', 2010,
  201.     'DLOG', 2020,
  202.     'DLOG', 10240,
  203.     'FOND', 19999,
  204.     'FOND', 32268,
  205.     'FREF', 128,
  206.     'FREF', 129,
  207.     'FREF', 130,
  208.     'FREF', 131,
  209.     'FREF', 132,
  210.     'FREF', 133,
  211.     'FREF', 134,
  212.     'GU∑I', 10240,
  213.     'ICN#', 10240,
  214.     'ICN#', 128,
  215.     'ICN#', 129,
  216.     'ICN#', 130,
  217.     'ICN#', 131,
  218.     'ICN#', 385,
  219.     'ICN#', 386,
  220.     'ICN#', 387,
  221.     'IRng', 128,
  222.     'LDEF', 128,
  223.     'MDEF', 1,
  224.     'MENU', 128,
  225.     'MENU', 129,
  226.     'MENU', 130,
  227.     'MENU', 131,
  228.     'MENU', 132,
  229.     'MENU', 192,
  230.     'McPL', 0,
  231.     'MrP#', 128,
  232.     'MrP4', 128,
  233.     'MrP8', 128,
  234.     'MrPA', 4096,
  235.     'MrPB', 128,
  236.     'MrPC', 0,
  237.     'MrPC', 1,
  238.     'MrPC', 2,
  239.     'MrPD', 4096,
  240.     'MrPF', 132,
  241.     'MrPF', 133,
  242.     'MrPF', 134,
  243.     'MrPI', 128,
  244.     'MrPL', 0,
  245.     'MrPS', -1,
  246.     'NFNT', 2816,
  247.     'NFNT', 2825,
  248.     'NFNT', 2828,
  249.     'NFNT', 32268,
  250.     'PICT', 128,
  251.     'SIZE', -1,
  252.     'STR ', 133,
  253.     'STR#', 129,
  254.     'STR#', 130,
  255.     'STR#', 132,
  256.     'STR#', 256,
  257.     'STR#', 32268,
  258.     'STR#', 384,
  259.     'TMPL', 10240,
  260.     'WIND', 128,
  261.     'WIND', 129,
  262.     'WIND', 130,
  263.     'acur', 0,
  264.     'acur', 128,
  265.     'acur', 129,
  266.     'aete', 0,
  267.     'dctb', 384,
  268.     'hmnu', 129,
  269.     'hmnu', 130,
  270.     'hmnu', 132,
  271.     'icl4', 128,
  272.     'icl4', 129,
  273.     'icl4', 130,
  274.     'icl4', 131,
  275.     'icl4', 385,
  276.     'icl4', 386,
  277.     'icl4', 387,
  278.     'icl8', 128,
  279.     'icl8', 129,
  280.     'icl8', 130,
  281.     'icl8', 131,
  282.     'icl8', 385,
  283.     'icl8', 386,
  284.     'icl8', 387,
  285.     'icm#', 256,
  286.     'icm#', 257,
  287.     'icm#', 264,
  288.     'icm#', 265,
  289.     'icm#', 266,
  290.     'ics#', 128,
  291.     'vers', 1,
  292.     'vers', 2,
  293.     0,      0
  294. };
  295.  
  296. OwnerList * noOwnerPtr = noOwner;
  297. OwnerList * ancientOwnerPtr = ancientOwner;
  298.  
  299. Boolean InOwnerList(OSType type, short id, OwnerList * list)
  300. {
  301.     while (list->type)
  302.         if (list->type == type && list->id == id)
  303.             return true;
  304.         else
  305.             ++list;
  306.     
  307.     return false;
  308. }
  309.  
  310. OSErr CopySomeResources(short origFile, short resFile)
  311. {
  312.     OSErr                err;
  313.     Handle             rsrc;
  314.     Handle            nur;
  315.     short                typeCnt;
  316.     short                typeIdx;
  317.     short                rsrcCnt;
  318.     short                rsrcIdx;
  319.     short                rsrcID;
  320.     Boolean            wantItBadly;
  321.     ResType            rsrcType;
  322.     Str255            rsrcName;
  323.     OwnerList **    include;
  324.     OwnerList **    exclude;
  325.     
  326.     UseResFile(origFile);
  327.     
  328.     if (!(exclude = (OwnerList **) Get1Resource('McPo', 128)))
  329.         exclude = &ancientOwnerPtr;
  330.  
  331.     if (!(include = (OwnerList **) Get1Resource('McPo', 129)))
  332.         include = &noOwnerPtr;
  333.     
  334.     typeCnt = Count1Types();
  335.     
  336.     for (typeIdx = 0; typeIdx++ < typeCnt; ) {
  337.         Get1IndType(&rsrcType, typeIdx);
  338.         
  339.         rsrcCnt = Count1Resources(rsrcType);
  340.         
  341.         for (rsrcIdx = 0; rsrcIdx++ < rsrcCnt; ) {
  342.             rsrc = Get1IndResource(rsrcType, rsrcIdx);
  343.             
  344.             if (!rsrc) 
  345.                 return ResError();
  346.             
  347.             GetResInfo(rsrc, &rsrcID, &rsrcType, rsrcName);
  348.             
  349.             if (rsrcType == 'McPo' && rsrcID == 128)
  350.                 continue;
  351.             if (rsrcType == 'McPo' && rsrcID == 129) {
  352.                 wantItBadly = true;
  353.                 HandToHand(&rsrc);
  354.             } else {
  355.                 wantItBadly = InOwnerList(rsrcType, rsrcID, *include);
  356.                 DetachResource(rsrc);
  357.             }
  358.             
  359.             if (wantItBadly || !InOwnerList(rsrcType, rsrcID, *exclude)) {
  360.                 UseResFile(resFile);
  361.         
  362.                 if (nur = Get1Resource(rsrcType, rsrcID))
  363.                     if (wantItBadly) {
  364.                         RmveResource(nur);
  365.                         
  366.                         nur = nil;
  367.                     }
  368.                 
  369.                 if (!nur) {    
  370.                     AddResource(rsrc, rsrcType, rsrcID, rsrcName);
  371.                 
  372.                     if (err = ResError()) {
  373.                         DisposeHandle(rsrc);
  374.                         return err;
  375.                     }
  376.                 } else 
  377.                     DisposeHandle(rsrc);
  378.                 
  379.                 UseResFile(origFile);
  380.             } else
  381.                 DisposeHandle(rsrc);
  382.         }
  383.     }
  384.     
  385.     return noErr;
  386. }
  387.  
  388. OSErr    CopyShoppingList(short from, short to, ShoppingList * list)
  389. {
  390.     OSErr            err;
  391.     
  392.     for (; list->type; ++list) {
  393.         Handle    rsrc;
  394.         Handle    nur;
  395.                 
  396.         UseResFile(from);
  397.         
  398.         rsrc = Get1Resource(list->type, list->id);
  399.         
  400.         if (!rsrc)
  401.             return ResError();
  402.         
  403.         UseResFile(to);
  404.         
  405.         if (nur = Get1Resource(list->realType, list->realID))
  406.             RmveResource(nur);
  407.             
  408.         HandToHand(&rsrc);
  409.         AddResource(rsrc, list->realType, list->realID, (StringPtr) "\p");
  410.         
  411.         if (err = ResError())
  412.             goto finish;
  413.         
  414. nextrsrc:
  415.         ;
  416.     }
  417.     
  418. finish:
  419.     UseResFile(from);
  420.     
  421.     return err;
  422. }
  423.  
  424. #if !defined(powerc) && !defined(__powerc)
  425. #pragma segment File
  426. #endif
  427.  
  428. static OSType    WantsType;
  429. static OSType    WantsCreator;
  430. static Boolean    WantsBundle;
  431. static Boolean    HasCustomIcon;
  432.  
  433. OSErr DoOpenResFile(FSSpec * spec, short * resFile)
  434. {
  435.     OSErr    err;
  436.     FInfo info;
  437.     
  438.     *resFile = HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdWrPerm);
  439.     if (*resFile == -1) {
  440.         if (err = DoCreate(*spec))
  441.             return err;
  442.  
  443.         *resFile =  HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdWrPerm);
  444.         if (*resFile == -1) {
  445.             FileError((StringPtr) "\perror opening file ", spec->name);
  446.             
  447.             return ResError();
  448.         }
  449.     }
  450.     
  451.     HGetFInfo(spec->vRefNum, spec->parID, spec->name, &info);
  452.     
  453.     info.fdType        =    WantsType;
  454.     info.fdCreator    =    WantsCreator;
  455.     
  456.     if (WantsBundle)
  457.         info.fdFlags     |= kHasBundle;
  458.     if (HasCustomIcon)
  459.         info.fdFlags     |= kHasCustomIcon;
  460.         
  461.     HSetFInfo(spec->vRefNum, spec->parID, spec->name, &info);
  462.     
  463.     return noErr;
  464. }
  465.  
  466. OSErr CopyRsrc(FSSpec * from, FSSpec * to)
  467. {
  468.     OSErr        err;
  469.     short     res;
  470.     short        fromRef;
  471.     short        toRef;
  472.     Handle    copy;
  473.     Ptr        buffer;
  474.     long        len;
  475.     
  476.     copy         = NewHandle(4096);
  477.     buffer     = *copy;
  478.     HLock(copy);
  479.     
  480.     if (err = DoOpenResFile(to, &res))
  481.         goto disposeBuffer;
  482.     
  483.     CloseResFile(res);
  484.     
  485.     if (err = HOpenRF(from->vRefNum, from->parID, from->name, fsRdPerm, &fromRef))
  486.         goto disposeBuffer;
  487.     if (err = HOpenRF(to->vRefNum, to->parID, to->name, fsRdWrPerm, &toRef))
  488.         goto closeFrom;
  489.  
  490.     do {
  491.         len    =    4096;
  492.         
  493.         FSRead(fromRef, &len, buffer);
  494.         FSWrite(toRef, &len, buffer);
  495.     } while (len == 4096);
  496.     
  497.     FSClose(toRef);
  498.     
  499. closeFrom:
  500.     FSClose(fromRef);
  501. disposeBuffer:
  502.     DisposeHandle(copy);
  503.     
  504.     return err;
  505. }
  506.  
  507. OSErr MakePackage(FSSpec * spec, short * resFile, DocType type)
  508. {
  509.     OSErr                    err;
  510.     short                    index;
  511.     short                    packFile;
  512.     ShoppingListHdl    shopping;
  513.  
  514.     BuildSEList();
  515.     
  516.     for (index = 0; index < (*SaveExtensions)->count; ++index)
  517.         if ((*SaveExtensions)->ext[index].id == type)
  518.             break;
  519.     
  520.     if (index == (*SaveExtensions)->count)
  521.         return errAEWrongDataType;
  522.  
  523.     WantsType         = (*SaveExtensions)->ext[index].fType;
  524.     WantsCreator    = (*SaveExtensions)->ext[index].fCreator;
  525.     WantsBundle        = (*SaveExtensions)->ext[index].wantsBundle;
  526.     HasCustomIcon    = (*SaveExtensions)->ext[index].hasCustomIcon;
  527.  
  528.     if (err = DoOpenResFile(spec, resFile))
  529.         return err;
  530.     
  531.     {
  532.         FSSpec *    spec = &(*SaveExtensions)->ext[index].file;
  533.         
  534.         packFile = HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdPerm);
  535.     }
  536.     
  537.     if (packFile == -1) {
  538.         err = fnfErr;
  539.         goto done;
  540.     }
  541.     
  542.     if (!(shopping = (ShoppingListHdl) Get1Resource('McPs', SERsrcBase))) {
  543.         err = ResError();
  544.         goto closePackage;
  545.     }
  546.     
  547.     HLock((Handle) shopping);
  548.     err = CopyShoppingList(packFile, *resFile, *shopping);
  549.  
  550. closePackage:
  551.     CloseResFile(packFile);
  552. done:    
  553.     if (err)
  554.         CloseResFile(*resFile);
  555.  
  556.     UseResFile(gAppFile);
  557.         
  558.     return err;
  559. }
  560.  
  561. ShoppingList Runtime7Shopping[] =
  562. {
  563.     { 'MrPB',  128, 'BNDL' },
  564.     { 'MrPI',  128, 'ICN#' },
  565.     { 'MrP4',  128, 'icl4' },
  566.     { 'MrP8',  128, 'icl8' },
  567.     { 'MrP#',  128, 'ics#' },
  568.     {          0,    0,      0 }
  569. };
  570.  
  571. OSErr Make7Runtime(FSSpec * spec, short * resFile)
  572. {
  573.     OSErr        err;
  574.     FSSpec    from;
  575.     
  576.     from.vRefNum    =    gAppVol;
  577.     from.parID        =    gAppDir;
  578.     PLstrcpy(from.name, LMGetCurApName());
  579.  
  580.     if (err = CopyRsrc(&from, spec))
  581.         return err;
  582.         
  583.     if (err = DoOpenResFile(spec, resFile))
  584.         return err;
  585.         
  586.     return CopyShoppingList(gAppFile, *resFile, Runtime7Shopping);
  587. }
  588.  
  589. pascal OSErr DoSave(DPtr theDocument, FSSpec theFSSpec)
  590. {
  591.     OSErr               err;
  592.     short                resFile;
  593.     short                origFile;
  594.     Handle            text    =     (*theDocument->theText)->hText;
  595.     OwnerList **    exceptions;
  596.     Handle            thePHandle;
  597.     HHandle            theHHandle;
  598.     StringHandle    theAppName;
  599.  
  600.     HDelete(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name);
  601.     
  602.     switch (theDocument->type) {
  603.     case kPlainTextDoc:
  604.         {
  605.             short        refNum;
  606.             long        length;
  607.             
  608.             WantsCreator    =    MPAppSig;
  609.             WantsType        =    'TEXT';
  610.             WantsBundle        =    false;
  611.             HasCustomIcon    =    false;
  612.             
  613.             if (err = DoOpenResFile(&theFSSpec, &resFile))
  614.                 return err;
  615.             
  616.             if (err = 
  617.                 HOpenDF(
  618.                     theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name,
  619.                     fsRdWrPerm, &refNum)
  620.             ) {
  621.                 if (err = DoCreate(theFSSpec))
  622.                     goto closeResource;
  623.                 
  624.                 if (err =
  625.                     HOpenDF(
  626.                         theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name,
  627.                         fsRdWrPerm, &refNum)
  628.                 ) {
  629.                     FileError((StringPtr) "\perror opening file ", theFSSpec.name);
  630.                     
  631.                     goto closeResource;
  632.                 }
  633.             }
  634.             
  635.             length     = GetHandleSize(text);
  636.             
  637.             HLock(text);
  638.             
  639.             err = FSWrite(refNum, &length, *text);
  640.             
  641.             HUnlock(text);
  642.             FSClose(refNum);
  643.             
  644.             if (err)
  645.                 goto closeResource;
  646.         }
  647.         break;
  648.     default:
  649.         if (err = MakePackage(&theFSSpec, &resFile, theDocument->type))
  650.             return err;
  651.         
  652.         goto writeScript;
  653.     case kRuntime7Doc:
  654.         WantsCreator    =    MPRtSig;
  655.         WantsType        =    'APPL';
  656.         WantsBundle        =    true;
  657.         HasCustomIcon    =    false;
  658.  
  659.         if (err = Make7Runtime(&theFSSpec, &resFile))
  660.             return err;
  661.         
  662. writeScript:            
  663.         if (err = HandToHand(&text))
  664.             goto closeResource;
  665.         
  666.         UseResFile(resFile);
  667.         
  668.         AddResource(text, 'TEXT', 128, (StringPtr) "\p!");
  669.         if (err = ResError()) {
  670.             DisposeHandle(text);
  671.             
  672.             goto closeResource;
  673.         }
  674.         
  675.         if (err = PtrToHand(&theDocument->type, &text, 4))
  676.             goto closeResource;
  677.         
  678.         AddResource(text, 'MrPL', 128, (StringPtr) "\p");
  679.         if (err = ResError()) {
  680.             DisposeHandle(text);
  681.             
  682.             goto closeResource;
  683.         }
  684.             
  685.         break;
  686.     }
  687.     
  688.     /* write out the printer info */
  689.     if (theDocument->thePrintSetup) {
  690.         thePHandle = (Handle)theDocument->thePrintSetup;
  691.         HandToHand(&thePHandle);
  692.  
  693.         AddResource(thePHandle, 'TFSP', 255, (StringPtr) "\pPrinter Info");
  694.         err = ResError();
  695.         if (err = ResError()) {
  696.             ShowError((StringPtr) "\pAddResource TFSP", err);
  697.             goto closeResource;
  698.         }
  699.     }
  700.  
  701.     theHHandle = (HHandle)NewHandle(sizeof(HeaderRec));
  702.      HLock((Handle)theHHandle);
  703.  
  704.     (*theHHandle)->theRect     = theDocument->theWindow->portRect;
  705.     OffsetRect(
  706.         &(*theHHandle)->theRect,
  707.         -theDocument->theWindow->portBits.bounds.left,
  708.         -theDocument->theWindow->portBits.bounds.top);
  709.         
  710.     GetFontName((*(theDocument->theText))->txFont, (StringPtr) &(*theHHandle)->theFont);
  711.     
  712.     (*theHHandle)->theSize     = (*(theDocument->theText))->txSize;
  713.     (*theHHandle)->lastID      = theDocument->kind == kDocumentWindow ? theDocument->u.reg.lastID : 0;
  714.     (*theHHandle)->numSections = theDocument->kind == kDocumentWindow ? theDocument->u.reg.numSections : 0;
  715.  
  716.     HUnlock((Handle)theHHandle);
  717.  
  718.     AddResource((Handle)theHHandle, 'TFSS', 255, (StringPtr) "\pHeader Info");
  719.     if (err = ResError()) {
  720.         ShowError((StringPtr) "\pAddResource- TFSS", err);
  721.         goto closeResource;
  722.     }
  723.  
  724.     /*if we have any sections, write out the records and resources*/
  725.  
  726.     if (theDocument->kind == kDocumentWindow && theDocument->u.reg.numSections) {
  727.         /*now write out the section records*/
  728.         SaveSections(theDocument);
  729.  
  730.         /*write the latest versions of all editions to their containers*/
  731.  
  732.         WriteAllEditions(theDocument);
  733.     }
  734.  
  735.     if (theDocument->type == kPlainTextDoc) {
  736.         /*Now put an AppName in for Finder in 7.0*/
  737.     
  738.         theAppName = (StringHandle)NewHandle(8);
  739.         PLstrcpy(*theAppName,(StringPtr) "\pMacPerl");
  740.     
  741.         AddResource((Handle)theAppName, 'STR ', - 16396, (StringPtr) "\pFinder App Info");
  742.         if (err = ResError()) {
  743.             ShowError((StringPtr) "\pAppName", err);
  744.             goto closeResource;
  745.         }
  746.     }
  747.  
  748.     if (theDocument->kind == kDocumentWindow && theDocument->u.reg.everLoaded) {
  749.         /* Copy all resources that need copying */
  750.         
  751.         origFile = 
  752.             HOpenResFile(
  753.                 theDocument->u.reg.origFSSpec.vRefNum,
  754.                 theDocument->u.reg.origFSSpec.parID,
  755.                 theDocument->u.reg.origFSSpec.name,
  756.                 fsRdPerm);
  757.         if (origFile != -1) {
  758.             err = CopySomeResources(origFile, resFile);
  759.                 
  760.             CloseResFile(origFile);
  761.         } 
  762.         /* Otherwise, let's just assume the file had no resource fork */
  763.     }
  764.  
  765. closeResource:
  766.     CloseResFile(resFile);
  767.     UseResFile(gAppFile);
  768.     
  769.     return err;
  770. }
  771.  
  772. void ScanExtensions(OSType type, void (*found)(const FSSpec * spec, CInfoPBRec * info))
  773. {
  774.     OSErr            err;
  775.     short            runs;
  776.     short         index;
  777.     FSSpec        spec;
  778.     CInfoPBRec    info;
  779.     
  780.     spec.vRefNum    =    gAppVol;
  781.     spec.parID        =    gAppDir;
  782.     
  783.     FSpUp(&spec);
  784.     
  785.     for (runs = 0; runs++ < 2; Special2FSSpec(kExtensionFolderType, 0, 0, &spec)) {
  786.         if (FSpDown(&spec, (StringPtr) "\pMacPerl Extensions"))
  787.             continue;
  788.         if (FSpDown(&spec, (StringPtr) "\p"))
  789.             continue;
  790.         for (index = 1; !FSpIndex(&spec, index++); )
  791.             if (!FSpCatInfo(&spec, &info) && info.hFileInfo.ioFlFndrInfo.fdType == type)
  792.                 found(&spec, &info);
  793.     }
  794. }
  795.  
  796. void AddSaveExtension(const FSSpec * spec, CInfoPBRec * info)
  797. {
  798.     short                 res;
  799.     short                    index;
  800.     SEPackageHdl        pack;    
  801.     StringHandle        name;
  802.     SaveExtension *    ext;
  803.     OSType                fType;
  804.     
  805.     res = HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdPerm);
  806.     
  807.     if (res == -1)
  808.         return;
  809.         
  810.     if (!(pack = (SEPackageHdl) Get1Resource('McPp', SERsrcBase)))
  811.         goto closeIt;
  812.     
  813.     for (index = 0; index<(*SaveExtensions)->count; ++index)
  814.         if ((*pack)->id == (*SaveExtensions)->ext[index].id)
  815.             goto closeIt;
  816.     
  817.     name    =    (StringHandle) Get1Resource('STR ', SERsrcBase);
  818.     
  819.     SetHandleSize(
  820.         (Handle) SaveExtensions, GetHandleSize((Handle) SaveExtensions) + sizeof(SaveExtension));
  821.     
  822.     ext                         = (*SaveExtensions)->ext + (*SaveExtensions)->count++;
  823.     ext->id                    = (*pack)->id;
  824.     ext->fType                = (*pack)->fType;
  825.     ext->fCreator            = (*pack)->fCreator;
  826.     ext->wantsBundle        = (*pack)->wantsBundle;
  827.     ext->hasCustomIcon    = (*pack)->hasCustomIcon;
  828.     ext->name        = name;
  829.     ext->file         = *spec;
  830.     
  831.     DetachResource((Handle) name);
  832.     
  833.     fType = ext->fType;
  834.     
  835.     for (index = 0; index<MacPerlFileTypeCount; ++index)
  836.         if (fType == ext->fType)
  837.             goto closeIt;
  838.     
  839.     PtrAndHand(&fType, (Handle) FileTypeH, sizeof(OSType));
  840.     
  841.     ++MacPerlFileTypeCount;
  842. closeIt:
  843.     CloseResFile(res);
  844. }
  845.  
  846. pascal void BuildSEList()
  847. {
  848.     if (SaveExtensions)
  849.         return;
  850.     
  851.     SaveExtensions                 = (SEHdl) NewHandle(2);
  852.     (*SaveExtensions)->count     = 0;
  853.     
  854.     PtrToHand("APPLTEXT", (Handle *) &FileTypeH, 8);
  855.     MacPerlFileTypeCount            = 2;
  856.     
  857.     ScanExtensions('McPp', AddSaveExtension);
  858.     
  859.     MoveHHi((Handle) FileTypeH);
  860.     HLock((Handle) FileTypeH);
  861.     
  862.     MacPerlFileTypes                = *FileTypeH;
  863. }
  864.  
  865. pascal Boolean CanSaveAs(DocType type)
  866. {
  867.     short    index;
  868.     
  869.     BuildSEList();
  870.     
  871.     switch (type) {
  872.     case kPlainTextDoc:
  873.     case kRuntime7Doc:
  874.         return true;
  875.     default:
  876.         break;
  877.     }
  878.     
  879.     for (index = 0; index<(*SaveExtensions)->count; ++index)
  880.         if (type == (*SaveExtensions)->ext[index].id)
  881.             return true;
  882.             
  883.     return false;
  884. }
  885.  
  886.  
  887. pascal void AddExtensionsToMenu(MenuHandle menu)
  888. {
  889.     short                index;
  890.     StringHandle    name;
  891.     
  892.     BuildSEList();
  893.     
  894.     for (index = 0; index < (*SaveExtensions)->count; ++index) {
  895.         name = (*SaveExtensions)->ext[index].name;
  896.         
  897.         HLock((Handle) name);
  898.         AppendMenu(menu, (StringPtr) "\px");
  899.         SetMenuItemText(menu, index+ssd_Predef+1, *name);
  900.         HUnlock((Handle) name);
  901.     }
  902. }
  903.  
  904. pascal short Type2Menu(DocType type)
  905. {
  906.     short    index;
  907.  
  908.     BuildSEList();
  909.     
  910.     switch (type) {
  911.     case kPlainTextDoc:
  912.         return 1;
  913.     case kRuntime7Doc:
  914.         return 2;
  915.     default:
  916.         for (index = 0; index < (*SaveExtensions)->count; ++index)
  917.             if ((*SaveExtensions)->ext[index].id == type)
  918.                 return index + ssd_Predef + 1;
  919.     }
  920.     
  921.     /* Should never happen */
  922.     
  923.     return 0;
  924. }
  925.  
  926. pascal DocType Menu2Type(short item)
  927. {
  928.     BuildSEList();
  929.     
  930.     switch (item) {
  931.     case 1:
  932.         return kPlainTextDoc;
  933.     case 2:
  934.         return kRuntime7Doc;
  935.     default:
  936.         item -= ssd_Predef + 1;
  937.         
  938.         if (item < 0 || item >= (*SaveExtensions)->count)
  939.             return kUnknownDoc;
  940.         
  941.         return (*SaveExtensions)->ext[item].id;
  942.     }
  943. }
  944.